package service

import (
	"fmt"
	"kubernate-server/conf"
	"net/http"
	"strconv"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"

	"github.com/gin-gonic/gin"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

/**
 * Author: 张文进
 * Description: deployments增删改查
 * Date: 2025-09-26
 */

type DeploymentService struct {
}

// 定义全局的结构体类型，供多个函数使用
type DeploymentRequest struct {
	Name     string            `json:"name" binding:"required"`
	Replicas int32             `json:"replicas" binding:"required"`
	Labels   map[string]string `json:"labels"`
	Image    string            `json:"image" binding:"required"`
	Port     int32             `json:"port"`
}

/*
*	获取Deployment的详情信息
 */
func (*DeploymentService) GetDeploymentDetail(ctx *gin.Context) {
	deploymentDetail, err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Get(ctx, ctx.Param("deploymentName"), metav1.GetOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "获取Deployment详情失败",
			"error":   err.Error(),
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code":       20000,
		"message":    "success",
		"name":       deploymentDetail.Name,
		"namespace":  deploymentDetail.Namespace,
		"replicas":   deploymentDetail.Status.Replicas,
		"ready":      deploymentDetail.Status.ReadyReplicas,
		"available":  deploymentDetail.Status.AvailableReplicas,
		"conditions": deploymentDetail.Status.Conditions,
		"labels":     deploymentDetail.Labels,
	})
}

/*
*	获取Deployment列表
 */
func (*DeploymentService) GetDeploymentList(ctx *gin.Context) {
	deploymentList, err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).List(ctx, metav1.ListOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "获取Deployment列表失败",
			"error":   err.Error(),
		})
		return
	}

	// 简化返回数据，只返回关键信息
	var simplifiedList []gin.H
	for _, deployment := range deploymentList.Items {
		simplifiedList = append(simplifiedList, gin.H{
			"name":      deployment.Name,
			"namespace": deployment.Namespace,
			"replicas":  deployment.Status.Replicas,
			"ready":     deployment.Status.ReadyReplicas,
			"available": deployment.Status.AvailableReplicas,
			"created":   deployment.CreationTimestamp,
		})
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":           20000,
		"message":        "success",
		"deploymentList": simplifiedList,
		"total":          len(deploymentList.Items),
	})
}

/*
*	创建Deployment
 */
func (*DeploymentService) CreateDeployment(ctx *gin.Context) {
	var deploymentReq DeploymentRequest

	if err := ctx.ShouldBindJSON(&deploymentReq); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"message": "请求参数错误",
			"error":   err.Error(),
		})
		return
	}

	deployment := createDeploymentReq2K8s(ctx.Param("nameSpace"), deploymentReq)
	_, err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Create(ctx, deployment, metav1.CreateOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "创建Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
		"data": gin.H{
			"name":      deploymentReq.Name,
			"namespace": ctx.Param("nameSpace"),
		},
	})
}

// 转换k8s数据结构
func createDeploymentReq2K8s(namespace string, req DeploymentRequest) *appsv1.Deployment {
	if req.Labels == nil {
		req.Labels = map[string]string{
			"app": req.Name,
		}
	}

	deployment := &appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      req.Name,
			Namespace: namespace,
			Labels:    req.Labels,
		},
		Spec: appsv1.DeploymentSpec{
			Replicas: &req.Replicas,
			Selector: &metav1.LabelSelector{
				MatchLabels: req.Labels,
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: req.Labels,
				},
				Spec: corev1.PodSpec{
					Containers: []corev1.Container{
						{
							Name:  req.Name,
							Image: req.Image,
							Ports: []corev1.ContainerPort{},
						},
					},
				},
			},
		},
	}

	// 如果指定了端口，添加端口配置
	if req.Port > 0 {
		deployment.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{
			{
				Name:          "http",
				ContainerPort: req.Port,
				Protocol:      corev1.ProtocolTCP,
			},
		}
	}

	return deployment
}

/*
*	更新Deployment
 */
func (*DeploymentService) UpdateDeployment(ctx *gin.Context) {
	var updateReq struct {
		Image string `json:"image" binding:"required"`
	}

	if err := ctx.ShouldBindJSON(&updateReq); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"message": "请求参数错误",
			"error":   err.Error(),
		})
		return
	}

	// 获取现有的Deployment
	deployment, err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Get(ctx, ctx.Param("deploymentName"), metav1.GetOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "获取Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	// 更新镜像版本
	if len(deployment.Spec.Template.Spec.Containers) > 0 {
		deployment.Spec.Template.Spec.Containers[0].Image = updateReq.Image
	}

	// 添加更新注释
	if deployment.Annotations == nil {
		deployment.Annotations = make(map[string]string)
	}
	deployment.Annotations["updated-by"] = "kubernate-server"
	deployment.Annotations["updated-at"] = metav1.Now().String()

	_, err = conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Update(ctx, deployment, metav1.UpdateOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "更新Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
		"data": gin.H{
			"name":      deployment.Name,
			"namespace": deployment.Namespace,
			"image":     updateReq.Image,
		},
	})
}

/*
*	扩缩容Deployment
 */
func (*DeploymentService) ScaleDeployment(ctx *gin.Context) {
	replicasStr := ctx.Param("replicas")
	replicas, err := strconv.ParseInt(replicasStr, 10, 32)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"message": "副本数参数错误",
			"error":   err.Error(),
		})
		return
	}

	replicas32 := int32(replicas)
	if replicas32 < 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"message": "副本数不能为负数",
		})
		return
	}

	// 获取现有的Deployment
	deployment, err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Get(ctx, ctx.Param("deploymentName"), metav1.GetOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "获取Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	// 更新副本数
	deployment.Spec.Replicas = &replicas32

	// 添加扩缩容注释
	if deployment.Annotations == nil {
		deployment.Annotations = make(map[string]string)
	}
	deployment.Annotations["scaled-by"] = "kubernate-server"
	deployment.Annotations["scaled-at"] = metav1.Now().String()
	deployment.Annotations["previous-replicas"] = fmt.Sprintf("%d", *deployment.Spec.Replicas)

	_, err = conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Update(ctx, deployment, metav1.UpdateOptions{})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "扩缩容Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
		"data": gin.H{
			"name":      deployment.Name,
			"namespace": deployment.Namespace,
			"replicas":  replicas32,
		},
	})
}

/*
*	删除Deployment
 */
func (*DeploymentService) DeleteDeployment(ctx *gin.Context) {
	deletePolicy := metav1.DeletePropagationForeground
	err := conf.KuberConfigSet.AppsV1().Deployments(ctx.Param("nameSpace")).Delete(ctx, ctx.Param("deploymentName"), metav1.DeleteOptions{
		PropagationPolicy: &deletePolicy,
	})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"message": "删除Deployment失败",
			"error":   err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
		"data": gin.H{
			"name":      ctx.Param("deploymentName"),
			"namespace": ctx.Param("nameSpace"),
		},
	})
}
